<template>
  <Card class="article-list" :bordered="false">
    <template #title> 文章列表 （{{ article.pagination?.total ?? '-' }}） </template>
    <template #extra>
      <router-link to="/article/post">
        <Button type="primary" size="small">
          <template #icon>
            <PlusOutlined />
          </template>
          新撰文章
        </Button>
      </router-link>
    </template>
    <Space class="toolbar" align="center">
      <Space direction="vertical">
        <Space>
          <Select
            :loading="loading.state.value"
            class="select"
            :value="filterParams.state"
            @change="(state: any) => (filterParams.state = state)"
          >
            <SelectOption :value="SELECT_ALL_VALUE">全部状态</SelectOption>
            <SelectOption v-for="(state, index) in publishStates" :key="index" :value="state.id">
              <Space> <component :is="state.icon" />{{ state.name }} </Space>
            </SelectOption>
          </Select>
          <Select
            :loading="loading.state.value"
            class="select"
            :value="filterParams.public"
            @change="(state: any) => (filterParams.public = state)"
          >
            <SelectOption :value="SELECT_ALL_VALUE">全部可见</SelectOption>
            <SelectOption v-for="(state, index) in articlePublics" :key="index" :value="state.id">
              <Space> <component :is="state.icon" />{{ state.name }} </Space>
            </SelectOption>
          </Select>
          <Select
            :loading="loading.state.value"
            class="select"
            :value="filterParams.origin"
            @change="(origin: any) => (filterParams.origin = origin)"
          >
            <SelectOption :value="SELECT_ALL_VALUE"> 全部来源 </SelectOption>
            <SelectOption v-for="(state, index) in articleOrigins" :key="index" :value="state.id">
              <Space> <component :is="state.icon" />{{ state.name }} </Space>
            </SelectOption>
          </Select>
          <Select
            :loading="loading.state.value"
            class="select"
            :value="filterParams.lang"
            @change="(state: any) => (filterParams.lang = state)"
          >
            <SelectOption :value="SELECT_ALL_VALUE"> 全部语言 </SelectOption>
            <SelectOption v-for="(state, index) in articleLanguages" :key="index" :value="state.id">
              <Space> <component :is="state.icon" />{{ state.name }} </Space>
            </SelectOption>
          </Select>
          <Select
            :loading="loadingTag.state.value"
            class="tagSelect"
            v-model:value="filterParams.tag_slug"
            @change="(tag_slug: any) => (filterParams.tag_slug = tag_slug)"
          >
            <SelectOption :value="SELECT_ALL_VALUE"> 全部标签 </SelectOption>
            <SelectOption v-for="item in tags" :key="item._id" :value="item.slug">
              {{ item.name }}({{ item.articles_count }})
            </SelectOption>
          </Select>
          <TreeSelect
            :loading="loadingCategory.state.value"
            placeholder="选择父分类"
            class="categoriesSelect"
            v-model:value="filterParams.category_slug"
            tree-default-expand-all
            :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
            :tree-data="[
              {
                label: '全部分类',
                key: SELECT_ALL_VALUE,
                value: SELECT_ALL_VALUE,
              },
              ...getAntdTreeByTree({
                tree: categoriesTree,
                valuer: (c) => c.slug,
              }),
            ]"
          />
        </Space>
        <Space>
          <InputSearch
            :loading="loading.state.value"
            class="search"
            placeholder="输入文章标题、内容搜索"
            v-model:value="serarchKeyword"
            @change="(e: any) => (serarchKeyword = e.target.value!)"
            @search="handleSearch"
          ></InputSearch>
          <Button type="primary" :loading="loading.state.value" @click="resetParamsAndRefresh">
            <template #icon>
              <ReloadOutlined />
            </template>
            重置并刷新
          </Button>
        </Space>
      </Space>
      <Space>
        <Button type="primary" :disabled="!selectedIDs.length">
          <template #icon>
            <DeleteOutlined />
          </template>
          批量删除
        </Button>
      </Space>
    </Space>
    <Divider />
    <Table
      :loading="loading.state.value"
      :data-source="article.data"
      rowKey="_id"
      :row-selection="{ selectedRowKeys: selectedIDs, onChange: handleSelect }"
      :pagination="{
        pageSizeOptions: ['10', '20', '50'],
        current: article.pagination?.current_page,
        pageSize: article.pagination?.per_page,
        total: article.pagination?.total,
        showSizeChanger: true,
      }"
      @change="handlePaginate"
    >
      <TableColumn key="id" :width="60" title="ID" data-index="id" />
      <TableColumn key="content" :width="360" title="文章" data-index="content">
        <template #default="{ record }">
          <Card
            size="small"
            :bordered="true"
            :body-style="{
              'min-height': '100px',
              'backdrop-filter': 'blur(2px)',
            }"
            :style="{
              margin: '1rem 0',
              'background-position': 'center',
              'background-size': 'cover',
              'min-height': '100px',
              'background-image': `url(${record.thumbnail})`,
              'background-blend-mode': 'soft-light',
            }"
          >
            <CardMeta>
              <template #title>
                <!-- :style="{ 'margin-bottom': '5px' }" -->
                <TypographyTitle :level="5">{{ record.title }}</TypographyTitle>
              </template>
              <template #content>
                <!-- style="margin-bottom: 5px" -->
                <TypographyParagraph type="secondary" :ellipsis="{ rows: 2, expandable: true }">
                  {{ record.description }}
                </TypographyParagraph>
              </template>
            </CardMeta>
          </Card>
        </template>
      </TableColumn>
      <TableColumn key="archive" :width="130" title="归类" data-index="archive">
        <template #default="{ record }">
          <Space direction="vertical">
            <Space size="small" v-for="category in record.category" :key="category._id">
              <FolderOpenOutlined />
              {{ category.name }}
            </Space>
            <Space size="small" :wrap="true">
              <Tag v-for="tag in record.tag" :key="tag._id">
                <template #icon>
                  <TagOutlined />
                </template>
                {{ tag.name }}
              </Tag>
            </Space>
          </Space>
        </template>
      </TableColumn>
      <TableColumn key="follow" :width="150" title="被关注" data-index="follow">
        <template #default="{ record }">
          <Space direction="vertical">
            <Space size="small">
              <EyeOutlined />
              浏览 {{ record.meta?.views }} 次
            </Space>
            <Space size="small">
              <HeartOutlined />
              喜欢 {{ record.meta?.likes }} 次
            </Space>
            <Space size="small">
              <CommentOutlined />
              评论 {{ record.meta?.comments }} 次
            </Space>
          </Space>
        </template>
      </TableColumn>
      <TableColumn key="create_at" :width="230" title="更新周期" data-index="create_at">
        <template #default="{ record }">
          <Space direction="vertical">
            <span>最早发布：{{ stringToYMD(record.create_at!) }}</span>
            <span>最后更新：{{ stringToYMD(record.update_at!) }}</span>
          </Space>
        </template>
      </TableColumn>
      <TableColumn key="state" :width="120" title="状态" data-index="state">
        <template #default="{ record }">
          <Space direction="vertical">
            <Tag
              v-for="item in [ps(record.state), ap(record.public), ao(record.origin)]"
              :color="item?.color"
              :key="item?.id"
            >
              <template #icon>
                <component :is="item.icon" />
              </template>
              {{ item?.name }}
            </Tag>
          </Space>
        </template>
      </TableColumn>
      <TableColumn key="action" :width="110" title="操作" data-index="action">
        <template #default="{ record }">
          <Space direction="vertical">
            <router-link :to="`/article/edit/${record._id}`">
              <Button size="small" type="text" :block="true">
                <template #icon>
                  <EditOutlined />
                </template>
                文章详情
              </Button>
            </router-link>
            <template v-if="record.state === 0">
              <Button
                size="small"
                type="text"
                :block="true"
                @click="handleStateChange([record._id], 1)"
              >
                <template #icon>
                  <CheckOutlined />
                </template>
                <a-typography-text type="success">直接发布</a-typography-text>
              </Button>
            </template>
            <template v-else-if="record.state === 1">
              <Button
                size="small"
                type="text"
                :block="true"
                :danger="true"
                @click="handleStateChange([record._id], -1)"
              >
                <template #icon>
                  <DeleteOutlined />
                </template>
                移回收站
              </Button>
            </template>
            <template v-else-if="record.state === -1">
              <Button
                size="small"
                type="text"
                :block="true"
                @click="handleStateChange([record._id], 0)"
              >
                <template #icon>
                  <RollbackOutlined />
                </template>
                <a-typography-text type="warning">退至草稿</a-typography-text>
              </Button>
            </template>
            <Button
              size="small"
              type="link"
              :block="true"
              target="_blank"
              :href="getBlogArticleUrl(record.id)"
            >
              <template #icon>
                <LinkOutlined />
              </template>
              宿主页面
            </Button>
          </Space>
        </template>
      </TableColumn>
    </Table>
  </Card>
</template>

<script setup lang="ts">
import { ref, reactive, toRaw, watch, onMounted } from 'vue'
import {
  PlusOutlined,
  CheckOutlined,
  EditOutlined,
  DeleteOutlined,
  ReloadOutlined,
  FolderOpenOutlined,
  TagOutlined,
  EyeOutlined,
  HeartOutlined,
  CommentOutlined,
  RollbackOutlined,
  LinkOutlined,
} from '@ant-design/icons-vue'
import _ from 'lodash'
import {
  Button,
  Card,
  CardMeta,
  Divider,
  InputSearch,
  Modal,
  Select,
  SelectOption,
  Space,
  Table,
  TableColumn,
  TablePaginationConfig,
  Tag,
  TreeSelect,
  TypographyParagraph,
  TypographyTitle,
} from 'ant-design-vue'
import { useLoading } from '@/handcer'

import type { ArticleId, Article } from '@/constants/article'
import type { Tag as TagType } from '@/constants/tag'
import { getCategories, getAntdTreeByTree, CategoryTree } from '@/store/category'
import type { ResponsePaginationData } from '@/constants/request'
import { SortType } from '@/constants/sort'
import { ArticleOrigin, articleOrigins } from '@/constants/article/origin'
import { ArticlePublic, articlePublics } from '@/constants/article/public'
import { ArticleLanguage, articleLanguages } from '@/constants/article/language'
import { PublishState, ps, publishStates } from '@/constants/publish'
import { ao } from '@/constants/article/origin'
import { ap } from '@/constants/article/public'
import { stringToYMD } from '@/transformers/date'
import { getBlogArticleUrl } from '@/transformers/url'

import { getTags } from '@/store/tag'
import { getArticles, patchArticlesState } from '@/store/article'
import type { GetArticleParams } from '@/store/article'

type SelectAllType = typeof SELECT_ALL_VALUE
const SELECT_ALL_VALUE = 'ALL'
const DEFAULT_FILTER_PARAMS = Object.freeze({
  sort: SortType.Desc,
  tag_slug: SELECT_ALL_VALUE as SelectAllType | string,
  category_slug: SELECT_ALL_VALUE as SelectAllType | string,
  lang: SELECT_ALL_VALUE as SelectAllType | ArticleLanguage,
  public: SELECT_ALL_VALUE as SelectAllType | ArticlePublic,
  origin: SELECT_ALL_VALUE as SelectAllType | ArticleOrigin,
  state: SELECT_ALL_VALUE as SelectAllType | PublishState,
})

// 列表数据
const loading = useLoading()
const article = reactive<ResponsePaginationData<Article>>({
  data: [],
  pagination: undefined,
})

// 分类
const loadingCategory = useLoading()
const categoriesTree = ref<Array<CategoryTree>>([])
const fetchCategories = () => {
  loadingCategory.promise(getCategories({ per_page: 50 })).then((result) => {
    categoriesTree.value = result.tree
  })
}

// 标签
const loadingTag = useLoading()
const tags = ref<Array<TagType>>([])
const fetchTags = () => {
  loadingTag.promise(getTags({ per_page: 50 })).then((result) => {
    tags.value = result.data
  })
}

// 过滤参数
const serarchKeyword = ref<string>('')
const filterParams = reactive({
  ...DEFAULT_FILTER_PARAMS,
})

// 多选
const selectedIDs = ref<Array<string>>([])
const handleSelect = (ids: any[]) => {
  selectedIDs.value = ids
}

// 弹窗
// const activeEditDataIndex = ref<number | null>(null);
// const isVisibleModal = ref<boolean>(false);
// const activeEditData = computed(() => {
//   const index = activeEditDataIndex.value;
//   return index !== null ? article.data[index] : null;
// });

// // 编辑创建
// const editData = (index: number) => {
//   activeEditDataIndex.value = index;
//   isVisibleModal.value = true;
// };

const handleSearch = () => {
  fetchData()
}

const fetchData = (params?: GetArticleParams) => {
  const getParams: any = {
    ...params,
    ...filterParams,
    keyword: serarchKeyword.value ? serarchKeyword.value : undefined,
  }
  Object.keys(getParams).forEach((paramKey) => {
    if (getParams[paramKey] === SELECT_ALL_VALUE) {
      Reflect.deleteProperty(getParams, paramKey)
    }
  })
  loading.promise(getArticles(getParams)).then((response) => {
    article.data = response.data
    article.pagination = response.pagination
  })
}

const resetParamsAndRefresh = () => {
  serarchKeyword.value = ''
  if (_.isEqual(toRaw(filterParams), DEFAULT_FILTER_PARAMS)) {
    fetchData()
  } else {
    Object.keys(DEFAULT_FILTER_PARAMS).forEach((paramKey) => {
      // @ts-ignore
      filterParams[paramKey] = Reflect.get(DEFAULT_FILTER_PARAMS, paramKey)
    })
  }
}

// 翻页
const handlePaginate = (pagination: TablePaginationConfig) => {
  const { current, pageSize } = pagination
  fetchData({ page: current, per_page: pageSize })
}

// 重新刷新数据
const refreshData = () => {
  fetchData({
    page: article.pagination?.current_page,
    per_page: article.pagination?.per_page,
  })
}

const handleStateChange = (articleIds: Array<ArticleId>, state: PublishState) => {
  Modal.confirm({
    title: `确定要将 ${articleIds.length} 个文章更新为「 ${ps(state).name} 」状态吗？`,
    content: '操作不可撤销',
    centered: true,
    onOk() {
      return patchArticlesState(articleIds, state).then(() => {
        refreshData()
      })
    },
  })
}

// 监听过滤参数重刷数据
watch(filterParams, () => fetchData())

onMounted(() => {
  fetchData()
  fetchCategories()
  fetchTags()
})
</script>
<style lang="less" scoped>
.article-list {
  .toolbar {
    display: flex;
    justify-content: space-between;
    .select {
      width: 120px;
    }
    .tagSelect {
      width: 160px;
    }
    .search {
      width: 280px;
    }
    .categoriesSelect {
      width: 230px;
    }
  }
}
</style>
